package net.wisos.opn.account.service;

import java.util.ArrayList;
import java.util.List;

import net.wisos.opn.account.dao.RoleDao;
import net.wisos.opn.account.dao.UserDao;
import net.wisos.opn.account.entity.Role;
import net.wisos.opn.account.entity.User;
import net.wisos.opn.service.ServiceException;

import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * 安全相关实体的管理类,包括用户和权限组.
 * 
 * @author steven
 */
@Component
@Transactional(readOnly = true)
public class AccountManager {
	private static Logger logger = LoggerFactory
			.getLogger(AccountManager.class);
	@Autowired
	private UserDao userDao;
	@Autowired
	private RoleDao roleDao;
	@Autowired(required = false)
	private ShiroDbRealm shiroRealm;

	private static final int CRYPTO_PASSWORD_LENGTH = 32;

	// -- User Manager --//
	public User getUser(Long id) {
		return userDao.findOne(id);
	}

	@Transactional(readOnly = false)
	public void saveUser(User user) {
		String password = user.getPassword();
		if (StringUtils.isBlank(password)) {
			logger.warn("用户密码不能为空。", SecurityUtils.getSubject().getPrincipal());
			throw new ServiceException("用户密码不能为空");
		}
		if (password.length() != CRYPTO_PASSWORD_LENGTH) {
			logger.warn("用户密码必须加密。", SecurityUtils.getSubject().getPrincipal());
			throw new ServiceException("用户密码必须加密。");
		}
		userDao.save(user);
		shiroRealm.clearCachedAuthorizationInfo(user.getLoginName());
	}

	public String encodePassword(String password) {
		return new Md5Hash(password).toString();
	}

	/**
	 * 删除用户,如果尝试删除超级管理员将抛出异常.
	 */
	@Transactional(readOnly = false)
	public void deleteUser(Long id) {
		if (isSupervisor(id)) {
			logger.warn("操作员{}尝试删除超级管理员用户", SecurityUtils.getSubject()
					.getPrincipal());
			throw new ServiceException("不能删除超级管理员用户");
		}
		userDao.delete(id);
	}

	/**
	 * 判断是否超级管理员.
	 */
	private boolean isSupervisor(Long id) {
		return id == 1;
	}

	public List<User> getAllUser() {
		return (List<User>) userDao.findAll(new Sort(Direction.ASC, "id"));
	}

	public User findUserByLoginName(String loginName) {
		return userDao.findByLoginName(loginName);
	}

	public Page<User> findUserByRole(Role role, Pageable pagealbe) {
		List<Role> roles = new ArrayList<Role>();
		roles.add(role);
		return userDao.findByRoles(roles, pagealbe);
	}

	public Page<User> findUserByRole(Long roleId, Pageable pagealbe) {
		Role role = new Role();
		role.setId(roleId);
		return findUserByRole(role, pagealbe);
	}

	// -- Role Manager --//
	public Role getRole(Long id) {
		return roleDao.findOne(id);
	}

	public List<Role> getAllRole() {
		return (List<Role>) roleDao.findAll((new Sort(Direction.ASC, "id")));
	}

	@Transactional(readOnly = false)
	public void saveRole(Role entity) {
		roleDao.save(entity);
		shiroRealm.clearAllCachedAuthorizationInfo();
	}

	@Transactional(readOnly = false)
	public void deleteRole(Long id) {
		roleDao.delete(id);
		shiroRealm.clearAllCachedAuthorizationInfo();
	}
}
